package ru.jexp.rcp.supply.swtext;

import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.IValueChangeListener;
import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
import org.eclipse.core.runtime.ListenerList;

import ru.jexp.mvc.Event;
import ru.jexp.mvc.IListener;
import ru.jexp.rcp.supply.ResultWrapper;

public class Lookup<ViewT extends Lookup.IView, ReturnedT> implements ILookup<ReturnedT>
{
	public interface IView
	{
		String CHOOSE_EVENT = "chooseEvent";

		IObservableValue getChooseEnabled();

		IObservableValue getChooseElement();
		
		IObservableValue getInputElements();
		
		void addChooseHandler(IListener listener);

		void create();

		int open();

		boolean close();
		
		void refresh();
	}

	private ViewT view;
	private ReturnedT chooseElement;
	private ListenerList listeners = new ListenerList();
	private Class<ReturnedT> type;

	public Lookup(ViewT view, Class<ReturnedT> type)
	{
		this.view = view;
		this.type = type;
	}

	@Override
	public int open(Object filter)
	{
		view.create();
		initInput(filter);
		addHandlers();
		return view.open();
	}

	@Override
	public void setChooseElement(ReturnedT chooseElement)
	{
		this.chooseElement = chooseElement;
	}

	@Override
	public ReturnedT getChooseElement()
	{
		return chooseElement;
	}
	
	protected void initInput(Object filter)
	{
		view.getInputElements().setValue(ResultWrapper.searchList(type));
	}

	protected void onSelection()
	{
	}

	@SuppressWarnings("unchecked")
	protected void onChoose()
	{
		ReturnedT oldValue = chooseElement;
		setChooseElement((ReturnedT) view.getChooseElement().getValue());
		fireChangeValueListener(oldValue, chooseElement);
	}

	protected ViewT getView()
	{
		return view;
	}

	@Override
	public void addChangeValueListener(IChangeValueListener<ReturnedT> listener)
	{
		listeners.add(listener);
	}
	
	@Override
	public void removeChangeValueListener(IChangeValueListener<ReturnedT> listener)
	{
		listeners.remove(listener);
	}
	
	@SuppressWarnings("unchecked")
	protected void fireChangeValueListener(ReturnedT oldValue, ReturnedT newValue)
	{
		Object[] copyListeners = listeners.getListeners();
		for (int i = 0; i < copyListeners.length; i++)
		{
			((IChangeValueListener<ReturnedT>) copyListeners[i]).valueChange(oldValue, newValue);
		}
	}

	protected void addHandlers()
	{
		view.getChooseEnabled().addValueChangeListener(new IValueChangeListener()
		{
			@Override
			public void handleValueChange(ValueChangeEvent event)
			{
				onSelection();
			}
		});
		view.addChooseHandler(new IListener()
		{
			@Override
			public void handle(Event e)
			{
				if (Boolean.TRUE.equals(view.getChooseEnabled().getValue()))
				{
					onChoose();
					view.close();
				}
			}
		});
	}

}
